iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
自我挑戰組

重新複習JavaScript系列 第 23

[Day -23] async function /await

  • 分享至 

  • xImage
  •  

前一篇我們講了Promise ,今天來把剩下的async function/await 講完。

Imgur

還記得這張圖嗎?

從Callback 變成 Promise,我們讓code變的:

  1. 有更清晰的code結構
  2. 處理錯誤更容易
  3. 避免再出現Callback Hell
  4. 更好的流程控制

那既然Promise這麼棒了,為什麼ES7還要再出一個async function/await 呢?

遇到不懂的趕快先去MDN 找一下資料:

The async function declaration creates a binding of a new async function to a given name. The await keyword is permitted within the function body, enabling asynchronous, promise-based behavior to be written in a cleaner style and avoiding the need to explicitly configure promise chains.

小小抱怨一下,MDN繁體中文版本的回答真的讓人一言難盡…

首先我要先修正一下自己的觀念,async function/await 的本質是 promise 的語法糖,它可以讓我們的Promise 程式碼的可讀性大大提升。

Promise 與 async, await

這句話怎麼說呢?我們來看一下兩者對於同一個功能寫法上的差異吧:

Promise:

const apiURL = `https://webdev.alphacamp.io/api/lyrics/Coldplay/Yellow.json`
function fetchResourceWithPromise(url) {
  return fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    })
    .then(data => {
      console.log(data);
    })
    .catch(error => {
      console.error('There was a problem:', error);
    });
}

fetchResourceWithPromise(apiURL);

Async function/await:

const apiURL = `https://webdev.alphacamp.io/api/lyrics/Coldplay/Yellow.json`
async function fetchResourceWithAsyncAwait(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('There was a problem:', error);
  }
}

fetchResourceWithAsyncAwait(apiURL);

對於一個剛接觸非同步觀念的新手來說,Async function/await 的方式會讓我更好理解,主要原因就在於 Async function/awaitthen 的串鏈轉換成了直接的 await ,減少了縮排和區塊的視覺干擾,較能在閱讀時專注於程式本身的邏輯。

接下來讓我們認識Async function/await

Async function/await

Async function

async function 可以用來定義一個非同步函式,讓這個 function 本體是屬於非同步,但其內部以“同步的方式運行非同步”程式碼。

基本寫法

我們只需要在定義 function 前加上 async 就可以使用 async function:

async function asyncFn() {
  return 'a';
}

asyncFn()

回傳值

一般來說,任何一個function裡面如果有return 都是會回傳return後面的值:

function asyncFn() {
  return 'a';
}
console.log(asyncFn());

Imgur

那如果是async function 呢?

我們來看看如果把async function console出來會是什麼:

async function asyncFn() {
  return 'a';
}
console.log(asyncFn());

Imgur

由於是以非同步的方式運行,因此我們無法得到 a 這個回傳值,但是我們得到了一個與 Promise 結構相似的函式,因此我們可以得知:

async function 被呼叫時會回傳一個Promise 物件。

這個 Promise 物件代表著當 asyncFn 非同步執行完成後,它的結果值會是 'a'。你可以使用 .then 來處理這個 Promise,以獲取最終的結果值。

asyncFn().then(result => {
  console.log(result); // 'a'
});

雖然我完全沒有用過這個語法就是了XD

Await

await 是屬於一元運算子,它會直接回傳後方表達式的值。

雖然是運算子,但是在原始碼中直接運行 await 則會出現錯誤,它只能在 async function 中運行,所以 async function/await 基本上是一體的,不會單獨出現。

另外await工作還未完成,就不會跑後面的程式碼,這樣的寫法使程式碼看起來更像我們前面提到的:async function本體是屬於非同步,但其內部以“同步的方式運行非同步

流程控制

async function/await 中的錯誤處理是使用 try...catch...

async function asyncFn() {
  try {
    const value = await somePromise();
    return value;
  } catch (err) {
    console.log('Oops, there was an error :(');
  }
}

asyncFn()

將正常情況下要執行的程式碼直接置入於 try 流程內,當遇到例外的錯誤時則撰寫在 catch 區塊內。


簡單的介紹一下,建議大家可以點擊下方的參考資料,觀看卡斯伯大大的文章,會更全面的了解。

但是必需再強調一次,async function/await 的本質是 promise 的語法糖,並不是一種全新的語法,因此了解promise 以及「非同步處理」觀念本身要很清楚,採用 async/await 目的是讓程式變好讀。

「仔細判讀程式流程」的基礎功一定要做紮實,程式流程沒想清楚,光是鑽研語法不足以解決問題,甚至可能會失焦。 By ALPHA Camp

參考資料:

https://www.casper.tw/development/2020/10/16/async-await/

https://pjchender.dev/javascript/js-async-await/


上一篇
[Day -22] Promise
下一篇
[Day -24] this
系列文
重新複習JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言